home *** CD-ROM | disk | FTP | other *** search
- unit TermAppU;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- StdCtrls, ExtCtrls, Buttons;
-
- type
- TMainForm = class(TForm)
- dlgOpen: TOpenDialog;
- btnLaunch1: TSpeedButton;
- btnLaunch2: TSpeedButton;
- btnTerminate1: TSpeedButton;
- btnTerminate2: TSpeedButton;
- procedure FormCreate(Sender: TObject);
- procedure btnLaunch1Click(Sender: TObject);
- procedure btnLaunch2Click(Sender: TObject);
- procedure btnTerminate1Click(Sender: TObject);
- procedure btnTerminate2Click(Sender: TObject);
- public
- HProcess: THandle;
- ProcessID: DWord;
- ThreadID: DWord;
- end;
-
- var
- MainForm: TMainForm;
-
- implementation
-
- uses
- ShellAPI, TermApp2U;
-
- {$R *.DFM}
-
- procedure TMainForm.FormCreate(Sender: TObject);
- var
- CString: array[0..Max_Path] of Char;
- begin
- //Set open dialog to look in Windows directory
- GetWindowsDirectory(CString, SizeOf(CString));
- dlgOpen.InitialDir := CString;
- end;
-
- procedure TMainForm.btnLaunch1Click(Sender: TObject);
- var
- SEI: TShellExecuteInfo;
- begin
- if dlgOpen.Execute then
- begin
- FillChar(SEI, SizeOf(SEI), 0);
- with SEI do
- begin
- cbSize := SizeOf(SEI);
- fMask := see_Mask_NoCloseProcess;
- Wnd := Application.Handle;
- lpFile := PChar(dlgOpen.FileName);
- lpParameters := nil;
- nShow := sw_ShowNormal;
- end;
- if ShellExecuteEx(@SEI) then
- begin
- HProcess := SEI.hProcess;
- ProcessID := 0;
- ThreadID := 0;
- WaitForInputIdle(HProcess, Infinite);
- btnLaunch1.Enabled := False;
- btnLaunch2.Enabled := False;
- btnTerminate1.Enabled := True;
- btnTerminate2.Enabled := False
- end
- end;
- end;
-
- procedure TMainForm.btnLaunch2Click(Sender: TObject);
- var
- SI: TStartupInfo;
- PI: TProcessInformation;
- begin
- if dlgOpen.Execute then
- begin
- GetStartupInfo(SI);
- Win32Check(CreateProcess(nil, PChar(dlgOpen.FileName), nil, nil, False, 0, nil, nil, SI, PI));
- //Save process information
- HProcess := PI.hProcess;
- ProcessID := PI.dwProcessId;
- ThreadID := PI.dwThreadId;
- btnLaunch1.Enabled := False;
- btnLaunch2.Enabled := False;
- btnTerminate1.Enabled := False;
- btnTerminate2.Enabled := True;
- WaitForInputIdle(HProcess, Infinite);
- end
- end;
-
- procedure TMainForm.btnTerminate1Click(Sender: TObject);
- begin
- TerminateProcess(HProcess, 1);
- btnLaunch1.Enabled := True;
- btnLaunch2.Enabled := True;
- btnTerminate1.Enabled := False;
- btnTerminate2.Enabled := False;
- end;
-
- function EnumFunc(Wnd: HWnd; TargetPID: DWord): Bool; stdcall;
- var
- PID: DWord;
- begin
- GetWindowThreadProcessId(Wnd, @PID);
- if PID = TargetPID then
- PostMessage(Wnd, wm_Close, 0, 0);
- Result := True;
- end;
-
- function CheckAppClosed(Process: THandle): Boolean;
- var
- OldTime: TDateTime;
- const
- mrEndTask = 100;
- mrWait = 101;
- begin
- Result := False;
- OldTime := Now;
- //Loop till either 10 sec is up, or program has terminated
- repeat
- //Do quick check on the app, but not long
- //enough to block (hang) this UI thread
- case WaitForSingleObject(Process, 100) of
- Wait_Object_0: Result := True;
- Wait_Failed: RaiseLastWin32Error;
- end;
- //Stop UI from hanging
- Application.ProcessMessages;
- //If user wants to shut, then fine
- if Application.Terminated then
- Break;
- until Result or (Now > OldTime + 10 / SecsPerDay);
-
- if not Result then //timeout has passed
- case ShutAppForm.ShowModal of
- mrEndTask:
- begin
- TerminateProcess(Process, 1);
- Result := True
- end;
- mrWait: {do nothing - we will loop again} ;
- mrCancel: Result := True;
- end
- end;
-
- procedure TMainForm.btnTerminate2Click(Sender: TObject);
- begin
- EnumWindows(@EnumFunc, LPARAM(ProcessID));
- //May need to do this whole 10 sec wait repeatedly
- repeat until CheckAppClosed(HProcess);
- btnLaunch1.Enabled := True;
- btnLaunch2.Enabled := True;
- btnTerminate1.Enabled := False;
- btnTerminate2.Enabled := False;
- end;
-
- end.
-